#include "ring_buffer.h"
#ifdef RING_BUFFER_USE_BIG_BLOCK_DATA
    #include <string.h>
#endif

/**
 * @brief 初始化环形缓冲区
 * @param buffer 环形缓冲区结构体指针
 * @param buffer_data 环形缓冲区数据指针
 * @param size 环形缓冲区大小
 * @return RING_BUFFER_SUCCESS 成功，RING_BUFFER_ERROR 失败
 */
int8_t ring_buffer_init(ring_buffer_t *buffer, uint8_t *buffer_data, uint32_t size)
{
    if(size < 2 || buffer_data == NULL || buffer == NULL)
    {
        return RING_BUFFER_ERROR;
    }
    buffer->buffer_data = buffer_data;      // 初始化缓冲区数据指针
    buffer->size = size;                    // 初始化缓冲区大小
    buffer->read_index = 0;                 // 初始化读取索引
    buffer->write_index = 0;                // 初始化写入索引
    buffer->count = 0;                      // 初始化缓冲区中的数据个数
    buffer->is_locked = 0;                  // 初始化缓冲区是否被锁定的标志
    return RING_BUFFER_SUCCESS;             // 返回成功
}

/**
 * @brief 释放环形缓冲区
 * @param buffer 环形缓冲区结构体指针
 * @return none
 */
void ring_buffer_free(ring_buffer_t *buffer)
{
    buffer->buffer_data = NULL;
    buffer->size = 0;
    buffer->read_index = 0;
    buffer->write_index = 0;
    buffer->count = 0;
    buffer->is_locked = 0;                  // 初始化缓冲区是否被锁定的标志
}

/**
 * @brief 获取环形缓冲区中可用的数据大小
 * @param buffer 环形缓冲区结构体指针
 * @return 可用的数据大小
 */
int ring_buffer_available(ring_buffer_t *buffer)
{
    return buffer->size - buffer->count;
}

/**
 * @brief 向环形缓冲区写入数据
 * @param buffer 环形缓冲区结构体指针
 * @param data 数据指针
 * @param size 数据大小
 * @return RING_BUFFER_SUCCESS 成功，RING_BUFFER_ERROR 失败
 */
int ring_buffer_write(ring_buffer_t *buffer, const uint8_t *data, uint32_t size)
{
    // 如果要写入的数据大小大于缓冲区可用空间，则返回RING_BUFFER_ERROR
    if (size > ring_buffer_available(buffer)) {
        return RING_BUFFER_ERROR;
    }
    // 检查缓冲区是否被锁定
    if(buffer->is_locked == RING_BUFFER_LOCK)
    {
        return RING_BUFFER_ERROR;
    }
    buffer->is_locked = RING_BUFFER_LOCK;                // 设置缓冲区被锁定的标志
#ifdef RING_BUFFER_USE_BIG_BLOCK_DATA
    // 如果顺序可用长度小于需写入的长度，需要将数据拆成两次分别写入
    if (buffer->size - buffer->write_index < size) {
        // 计算第一次写入的长度
        uint32_t first_write_size = buffer->size - buffer->write_index;
        // 将数据写入缓冲区
        memcpy(buffer->buffer_data + buffer->write_index, data, first_write_size);
        // 计算第二次写入的长度
        uint32_t second_write_size = size - first_write_size;
        // 将数据写入缓冲区
        memcpy(buffer->buffer_data, data + first_write_size, second_write_size);
        // 更新写入索引
        buffer->write_index = second_write_size;
    } else {
        // 将数据写入缓冲区
        memcpy(buffer->buffer_data + buffer->write_index, data, size);
        // 更新写入索引
        buffer->write_index += size;
        //如果写入数据后尾指针刚好写到数组尾部，则回到开头，防止越位
        if (buffer->write_index == buffer->size) {
            buffer->write_index = 0;
        }
    }
#else   // RING_BUFFER_USE_BIG_BLOCK_DATA
    uint32_t i;
    // 遍历要写入的数据
    for (i = 0; i < size; i++) {
        // 将数据写入缓冲区
        buffer->buffer_data[buffer->write_index] = data[i];
        // 更新写入索引
        buffer->write_index = (buffer->write_index + 1) % buffer->size;
    }
#endif  // RING_BUFFER_USE_BIG_BLOCK_DATA
    // 更新缓冲区中的数据个数
    buffer->count += size;
    // 设置缓冲区未被锁定的标志
    buffer->is_locked = RING_BUFFER_UNLOCK;
    // 返回成功
    return RING_BUFFER_SUCCESS;
}

/**
 * @brief 从环形缓冲区读取数据
 * @param buffer 环形缓冲区结构体指针
 * @param data 数据指针
 * @param size 数据大小
 * @return RING_BUFFER_SUCCESS 成功，RING_BUFFER_ERROR 失败
 */
int ring_buffer_read(ring_buffer_t *buffer, uint8_t *data, uint32_t size)
{
    // 如果要读取的数据大小大于缓冲区中的数据个数，则返回RING_BUFFER_ERROR
    if (size > buffer->count || data == NULL || buffer == NULL) {
        return RING_BUFFER_ERROR;
    }
    // 检查请求大小是否为0
    if (size == 0) {
        return RING_BUFFER_ERROR;
    }
    // 检查缓冲区是否被锁定
    if(buffer->is_locked == RING_BUFFER_LOCK)
    {
        return RING_BUFFER_ERROR;
    }
    buffer->is_locked = RING_BUFFER_LOCK;                // 设置缓冲区被锁定的标志
#ifdef RING_BUFFER_USE_BIG_BLOCK_DATA
    uint32_t onec_available_size = buffer->size - buffer->read_index;
    // 如果顺序可用长度小于需读取的长度，需要将数据拆成两次分别读取
    if (onec_available_size < size) {
        // 计算第一次读取的长度
        uint32_t first_read_size = onec_available_size;
        // 将数据从缓冲区读取
        memcpy(data, buffer->buffer_data + buffer->read_index, first_read_size);
        // 计算第二次读取的长度
        uint32_t second_read_size = size - first_read_size;
        // 将数据从缓冲区读取
        memcpy(data + first_read_size, buffer->buffer_data, second_read_size);
        // 更新读取索引
        buffer->read_index = second_read_size;
    } else {
        // 将数据从缓冲区读取
        memcpy(data, buffer->buffer_data + buffer->read_index, size);
        // 更新读取索引
        buffer->read_index += size;
        //如果读取数据后尾指针刚好写到数组尾部，则回到开头，防止越位
        if (buffer->read_index == buffer->size) {
            buffer->read_index = 0;
        }
    }
#else   // RING_BUFFER_USE_BIG_BLOCK_DATA
    uint32_t i;
    // 遍历要读取的数据
    for (i = 0; i < size; i++) {
        // 从缓冲区读取数据
        data[i] = buffer->buffer_data[buffer->read_index];
        // 更新读取索引
        buffer->read_index = (buffer->read_index + 1) % buffer->size;
    }
#endif  // RING_BUFFER_USE_BIG_BLOCK_DATA
    // 更新缓冲区中的数据个数
    buffer->count -= size;
    // 设置缓冲区未被锁定的标志
    buffer->is_locked = RING_BUFFER_UNLOCK;
    // 返回成功
    return RING_BUFFER_SUCCESS;
}
